import React from 'react';
import { InputTrigger } from '../../baseComponent';
import {
  BMap,
  compHoc,
  core,
  EnvironmentOutlined,
  initBMapSource,
  LoadingOutlined,
  registerComponent,
  useExtendRef,
  useRefState,
  useUpdateEffect,
  type IBMapProps,
  type PromiseType
} from '../../util';

export async function openBMap(
  props: IBMapProps
): Promise<PromiseType<{ closeStatus?: 'ok' | 'cancel'; value?: any }>> {
  await initBMapSource(props.ak);
  return new Promise((resolve) => {
    const apiRef = React.createRef<any>();
    const handleOk = async (ins) => {
      const value = apiRef.current?.getValue() ?? {};
      ins.destroy();
      resolve({
        value,
        closeStatus: 'ok'
      });
    };
    const handleCancel = (ins) => {
      const value = apiRef.current?.getValue() ?? {};
      ins.destroy();
      resolve({
        value,
        closeStatus: 'cancel'
      });
    };
    core.external.showModal({
      title: '地图',
      width: 1000,
      height: 700,
      body: { position: 'relative' },
      content: <BMap ref={apiRef} {...props} />,
      async onOk(ins) {
        await handleOk(ins);
      },
      async onCancel(ins) {
        await handleCancel(ins);
      }
    });
  });
}

/**
 * 百度地图回显组件
 */
export const InputBMap = compHoc<InputBMapProps>((p) => {
  const { value, onChange, outRef, labelInValue, labelField = 'address', disabled, ...props } = p;

  const valueToJson = () => (labelInValue ? core.parseJson(value) : value);

  const [state, setState] = useRefState({ loading: false, value: valueToJson() });

  useUpdateEffect(() => {
    setState({ value: valueToJson() });
  }, [value]);

  const onTrigger = async () => {
    const mapProps = { ...props };
    if (state.value) {
      if (labelInValue) {
        mapProps.point = state.value.point;
        if (!mapProps.point) {
          mapProps.address = state.value.address || state.value;
        }
      } else {
        mapProps.address = state.value;
      }
    }
    setState({ loading: true });
    const { closeStatus, value: v } = await openBMap(mapProps);
    if (closeStatus === 'ok') {
      const data = {
        ...v.address_detail,
        ...v.point,
        point: v.point,
        address: v.address,
        business: v.business
      };
      const newValue = labelInValue ? core.jsonString(data) : data[labelField];

      if (!p.hasOwnProperty('value') || !p.hasOwnProperty('onChange')) {
        setState({ value: newValue });
      }
      onChange?.(newValue, data);
    }
    setState({ loading: false });
  };

  const onClear = (v) => {
    !v && setState({ value: v });
  };

  useExtendRef(outRef, () => {
    return {
      getValue() {
        return state.value;
      },
      setValue(v) {
        if (state.value === v) {
          return;
        }
        setState({ value: v });
        onChange?.(v);
      }
    };
  });

  const getText = () => {
    return labelInValue ? state.value?.[labelField] || state.value : state.value;
  };

  return (
    <InputTrigger
      disabled={disabled}
      suffix={state.loading ? <LoadingOutlined /> : <EnvironmentOutlined />}
      editable={false}
      onChange={onClear}
      value={getText()}
      onTrigger={onTrigger}
    />
  );
});

registerComponent({ InputBMap });

interface InputBMapProps extends IBMapProps {
  value?: any;
  labelInValue?: boolean;
  disabled?: boolean;
  labelField?: string;
  onChange?: (...args) => void;
}
